﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MaxFramework;

namespace WebDownloader
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        public System.Text.Encoding tEncodingWindows1251 = System.Text.Encoding.GetEncoding("windows-1251");
        public const string BaseURL = "http://www.primemusic.ru/";
        public EventManager mEventManager = null;
        public QueueProcessor mQueueProcessor = null;
        public System.Threading.Thread mThread = null;
        public delegate string GetSourceDelegate(string pURL, System.Text.Encoding pEncoding);

        private void button1_Click(object sender, EventArgs e)
        {

            button1.Enabled = false;

            mThread = new System.Threading.Thread(new System.Threading.ThreadStart(Process));
            mThread.Start();


        }

        public string GetSource(string pURL, System.Text.Encoding pEncoding)
        {
            if (this.InvokeRequired)
            {
                return (string)this.Invoke(new GetSourceDelegate(GetSource), pURL, pEncoding);
            }
            else
            {
                string tResult = "";

                for (int i = 0; i <= 5; i++)
                {
                    try
                    {
                        var tRequest = System.Net.HttpWebRequest.Create(pURL);

                        using (var tResponse = tRequest.GetResponse())
                        {
                            using (System.IO.StreamReader sr = new System.IO.StreamReader(tResponse.GetResponseStream(), pEncoding))
                            {
                                tResult = sr.ReadToEnd();
                            }
                        }


                        break;
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine("retry(" + i.ToString() + ") " + ex.ToString());
                    }
                }
                return tResult;
            }
        }

        private int GetTotalPages()
        {

            var tMainFullUrl = string.Format("{0}Media-all.html", BaseURL);
            var tMainSource = Functions.GetSource(tMainFullUrl, tEncodingWindows1251);
            var tMainDocument = HTML.HtmlDocument.Create(tMainSource);
            var items = tMainDocument.GetElements("center", "span");
            var subitems = items.Where(t => t.Text == "...").ToList();
            var dotdotdot = subitems.FirstOrDefault();
            var nextitem = items[items.IndexOf(dotdotdot) + 1];
            var bitems = nextitem.Nodes.FindByName("b", true);

            return ((HTML.HtmlElement)bitems[0]).Text.IntValueOrZero();
        }

        private void Process()
        {


            List<string> tMasterList = new List<string>();
            var total = GetTotalPages();
            for (int i = 1; i <= total; i++)
            {
                var tFullUrl = string.Format("{0}Media-all-{1}.html", BaseURL, i);

                var tSource = Functions.GetSource(tFullUrl, tEncodingWindows1251);

                var tDocument = HTML.HtmlDocument.Create(tSource);

                var items = tDocument.GetAttributeValues("a", "href", @"Media\-page\-[0-9]+\.html");

                tMasterList.AddRange(items);

                mEventManager.UpdateProgress(138, i, "Processing Lists");
            }

            var files = new SortedList<string, string>();

            int j = 0;

            foreach (var tURL in tMasterList)
            {
                j++;

                mEventManager.UpdateProgress2(tMasterList.Count, j, string.Format("Processing URL: {0}", tURL));

                var tFullUrl = string.Format("{0}{1}", BaseURL, tURL);

                var tSource = GetSource(tFullUrl, tEncodingWindows1251);

                var tDocument = HTML.HtmlDocument.Create(tSource);

                var items = tDocument.GetAttributeValues("a", "href", @"Media\-download\-[0-9]+\.html");

                if (items.Count > 0)
                {
                    var id = System.Text.RegularExpressions.Regex.Replace(items[0], @"Media\-download\-([0-9]+)\.html", "$1");

                    if (mQueueProcessor.mMasterList.Find(t => t.DownloadID == id) == null)
                    {

                        var tNextFullUrl = string.Format("{0}{1}", BaseURL, items[0]);

                        tSource = GetSource(tNextFullUrl, tEncodingWindows1251);

                        tDocument = HTML.HtmlDocument.Create(tSource);

                        items = tDocument.GetAttributeValues("a", "href", @"http\:\/\/.*\.mp3");

                        if (items.Count > 0)
                        {
                            var tDownloadURL = items[0];

                            var filename = tDownloadURL.Substring(tDownloadURL.LastIndexOf("/") + 1);

                            if (!System.IO.File.Exists(string.Format(@".\completed\{0}", filename)) && !System.IO.File.Exists(string.Format(@".\downloading\{0}", filename)))
                            {
                                if (!files.ContainsKey(filename) && !files.ContainsValue(tDownloadURL))
                                {
                                    mQueueProcessor.QueueProcessItem(new QueueProcessor.ProcessItem()
                                    {
                                        Key = Guid.NewGuid(),
                                        EventManager = mEventManager,
                                        FileName = filename,
                                        URL = tDownloadURL,
                                        DownloadID = id
                                    });
                                }
                            }

                        }
                    }
                }
            }

        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            mEventManager = new EventManager();
            mEventManager.EventUpdateProgress2 += new EventManager.DelegateUpdateProgress2(mEventManager_EventUpdateProgress2);
            mEventManager.EventUpdateProgress += new EventManager.DelegateUpdateProgress(mEventManager_EventUpdateProgress);
            mEventManager.EventUpdateStatusLog += new EventManager.DelegateUpdateStatusLog(mEventManager_EventUpdateStatusLog);

            mQueueProcessor = new QueueProcessor(true, mEventManager);
        }

        public void mEventManager_EventUpdateStatusLog(Guid pKey, string pMessage)
        {
            if (InvokeRequired)
            {
                this.Invoke(new EventManager.DelegateUpdateStatusLog(mEventManager_EventUpdateStatusLog), pKey, pMessage);
            }
            else
            {
                var tListViewItem = listView1.Items.Cast<ListViewItem>().Where(t => (Guid)t.Tag == pKey).FirstOrDefault();

                if (tListViewItem == null)
                {
                    tListViewItem = listView1.Items.Add(pMessage);
                    tListViewItem.Tag = pKey;
                }
                else
                {
                    tListViewItem.Text = pMessage;
                }
            }

        }

        public void mEventManager_EventUpdateProgress2(int pTotal, int pCurrent, string pDescription)
        {
            if (InvokeRequired)
            {
                this.Invoke(new EventManager.DelegateUpdateProgress2(mEventManager_EventUpdateProgress2), pTotal, pCurrent, pDescription);
            }
            else
            {
                progressBar2.Maximum = pTotal;
                progressBar2.Value = pCurrent % pTotal;
                label2.Text = pDescription;
            }

        }

        public void mEventManager_EventUpdateProgress(int pTotal, int pCurrent, string pDescription)
        {
            if (InvokeRequired)
            {
                this.Invoke(new EventManager.DelegateUpdateProgress(mEventManager_EventUpdateProgress), pTotal, pCurrent, pDescription);
            }
            else
            {
                if (pCurrent == 0 && pTotal == 0) return;
                progressBar1.Maximum = pTotal;
                progressBar1.Value = pCurrent % pTotal;
                label1.Text = pDescription;
            }

        }

        private void txtMaxThreadCount_TextChanged(object sender, EventArgs e)
        {
            mQueueProcessor.mMaxThreads = txtMaxThreadCount.Text.IntValueOrZero();
        }

        private void btnSaveQueue_Click(object sender, EventArgs e)
        {
            mQueueProcessor.SaveQueue();
        }

        private void btnLoadQueue_Click(object sender, EventArgs e)
        {
            mQueueProcessor.LoadQueue();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            mQueueProcessor.Stop();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            mQueueProcessor.Start();
        }

    }
}
